import express from 'express'
import path from 'path'
import http from 'http'
import socket from 'socket.io'
import session from 'express-session'
import mongo from 'connect-mongo'
import flash from 'connect-flash'
import winston from 'winston'
import expressWinston from 'express-winston'
import helmet from 'helmet'
import ueditor from 'ueditor'
import routes from './routes'
import pkg from './package'
import configLite from 'config-lite'
import cookieParser from 'cookie-parser'

// import bodyParser from 'bodyParser' // 会导致POST请求无效，使用API时候再开启

const app = express()
const server = http.Server(app)
const io = socket(server)
const MongoStore = mongo(session)
const config = configLite(__dirname)

// https://cnodejs.org/topic/56f3b0e8dd3dade17726fe85 抵御一些比较常见的安全web安全隐患
app.use(helmet())
app.use(cookieParser())

// app.use(bodyParser.urlencoded({
//   extended: true
// }))
// app.use(bodyParser.json())

app.use(
  '/ueditor/ue',
  ueditor(path.join(__dirname, 'public'), function(req, res, next) {
    // 客户端上传文件设置
    const imgDir = '/img/ueditor/'
    const ActionType = req.query.action
    if (ActionType === 'uploadimage' || ActionType === 'uploadfile' || ActionType === 'uploadvideo') {
      let fileUrl = imgDir // 默认图片上传地址
      /* 其他上传格式的地址 */
      if (ActionType === 'uploadfile') {
        fileUrl = '/file/ueditor/' // 附件
      }
      if (ActionType === 'uploadvideo') {
        fileUrl = '/video/ueditor/' // 视频
      }
      res.ue_up(fileUrl) // 你只要输入要保存的地址 。保存操作交给ueditor来做
      res.setHeader('Content-Type', 'text/html')
    } else if (req.query.action === 'listimage') {
      // 客户端发起图片列表请求
      const dirUrl = imgDir
      res.ue_list(dirUrl) // 客户端会列出 dirUrl 目录下的所有图片
    } else {
      // 客户端发起其它请求
      // console.log('config.json')
      res.setHeader('Content-Type', 'application/json')
      res.redirect('/ueditor/nodejs/config.json')
    }
  })
)

// 设置模板目录
app.set('views', path.join(__dirname, 'views'))
// 设置模板引擎为 ejs
app.set('view engine', 'ejs')

// 设置静态文件目录
app.use(express.static(path.join(__dirname, 'public')))
// session 中间件
app.use(
  session({
    name: config.session.key, // 设置 cookie 中保存 session id 的字段名称
    secret: config.session.secret, // 通过设置 secret 来计算 hash 值并放在 cookie 中，使产生的 signedCookie 防篡改
    resave: true, // 强制更新 session
    saveUninitialized: false, // 设置为 false，强制创建一个 session，即使用户未登录
    cookie: {
      maxAge: config.session.maxAge // 过期时间，过期后 cookie 中的 session id 自动删除
    },
    store: new MongoStore({
      // 将 session 存储到 mongodb
      url: config.mongodb // mongodb 地址
    })
  })
)
// flash 中间件，用来显示通知
app.use(flash())

// 处理表单及文件上传的中间件
app.use(
  require('express-formidable')({
    uploadDir: path.join(__dirname, 'public/img'), // 上传文件目录
    keepExtensions: true // 保留后缀
  })
)

// 设置模板全局常量
app.locals.blog = {
  title: pkg.name,
  description: pkg.description
}

// 添加模板必需的三个变量
app.use(function(req, res, next) {
  res.locals.user = req.session.user
  res.locals.success = req.flash('success').toString()
  res.locals.error = req.flash('error').toString()
  next()
})

// 正常请求的日志
app.use(
  expressWinston.logger({
    transports: [
      new winston.transports.Console({
        json: true,
        colorize: true
      }),
      new winston.transports.File({
        filename: 'logs/success.log'
      })
    ]
  })
)
// 路由
routes(app)
// 错误请求的日志
app.use(
  expressWinston.errorLogger({
    transports: [
      new winston.transports.Console({
        json: true,
        colorize: true
      }),
      new winston.transports.File({
        filename: 'logs/error.log'
      })
    ]
  })
)

app.use(function(err, req, res, next) {
  console.error(err)
  req.flash('error', err.message)
  res.redirect('/')
})

if (module.parent) {
  // 被 require，则导出 app
  module.exports = app
} else {
  // 监听端口，启动程序
  server.listen(config.port, function() {
    console.log(`${pkg.name} listening on port ${config.port}`)
  })
}

// io.on('connection', function (socket) {
//   socket.emit('news', { hello: 'world' })
//   socket.on('my other event', function (data) {
//     console.log(data)
//   })
//   socket.on('tiwen', function (msg) {
//   // console.log( '提问为：' + msg );
//   // socket.emit('huida','好呀');
//   // 加上广播
//     io.emit('huida', msg)
//   })
// })

// 在线用户
var onlineUser = {}
var onlineCount = 0

io.on('connection', function(socket) {
  console.log('新用户登录')
  // 监听新用户加入
  socket.on('login', function(obj) {
    socket.name = obj.userid
    // 检查用户在线列表
    if (!onlineUser.hasOwnProperty(obj.userid)) {
      onlineUser[obj.userid] = obj.username
      // 在线人数+1
      onlineCount++
    }
    // 广播消息
    io.emit('login', { onlineUser: onlineUser, onlineCount: onlineCount, user: obj })
    console.log(obj.username + '加入了聊天室')
  })

  // 监听用户退出
  socket.on('disconnect', function() {
    // 将退出用户在在线列表删除
    if (onlineUser.hasOwnProperty(socket.name)) {
      // 退出用户信息
      var obj = { userid: socket.name, username: onlineUser[socket.name] }
      // 删除
      delete onlineUser[socket.name]
      // 在线人数-1
      onlineCount--
      // 广播消息
      io.emit('logout', { onlineUser: onlineUser, onlineCount: onlineCount, user: obj })
      console.log(obj.username + '退出了聊天室')
    }
  })

  // 监听用户发布聊天内容
  socket.on('message', function(obj) {
    // 向所有客户端广播发布的消息
    io.emit('message', obj)
    console.log(obj.username + '说：' + obj.content)
  })
})
